#ifndef __CUDA_GL_WRAPPER_H__
#define __CUDA_GL_WRAPPER_H__

#include <GL/gl.h>

#include "mc_gl_types.h"
#include "mc_runtime.h"

#if defined(WCUDA_API_PER_THREAD_DEFAULT_STREAM)
#define __WCUDA_API_PTDS(api) api##_ptds
#define __WCUDA_API_PTSZ(api) api##_ptsz
#else
#define __WCUDA_API_PTDS(api) api
#define __WCUDA_API_PTSZ(api) api
#endif

#define wcuGLCtxCreate            wcuGLCtxCreate_v2
#define wcuGLMapBufferObject      __WCUDA_API_PTDS(wcuGLMapBufferObject_v2)
#define wcuGLMapBufferObjectAsync __WCUDA_API_PTSZ(wcuGLMapBufferObjectAsync_v2)
#define wcuGLGetDevices           wcuGLGetDevices_v2

mcDrvError_t wcuGraphicsGLRegisterBuffer(mcDrvGraphicsResource *pMacaResource, GLuint buffer,
                                         unsigned int Flags);
mcDrvError_t wcuGraphicsGLRegisterImage(mcDrvGraphicsResource *pMacaResource, GLuint image,
                                        GLenum target, unsigned int Flags);
#if defined(_WIN32)
#if !defined(WGL_NV_gpu_affinity)
typedef void *HGPUNV;
#endif
mcDrvError_t wcuWGLGetDevice(mcDrvDevice_t *pDevice, HGPUNV hGpu);
#endif /* _WIN32 */

mcDrvError_t wcuGLGetDevices(unsigned int *pMacaDeviceCount, mcDrvDevice_t *pMacaDevices,
                             unsigned int mcDeviceCount, mcDrvGLDeviceList deviceList);
mcDrvError_t wcuGLMapBufferObject_v2(mcDrvDeviceptr_t *dptr, size_t *size, GLuint buffer);
mcDrvError_t wcuGLMapBufferObjectAsync_v2(mcDrvDeviceptr_t *dptr, size_t *size, GLuint buffer,
                                          mcDrvStream_t hStream);
mcDrvError_t wcuGLCtxCreate(mcDrvContext_t *pCtx, unsigned int Flags, mcDrvDevice_t device);
mcDrvError_t wcuGLMapBufferObject(mcDrvDeviceptrv1_t *dptr, unsigned int *size, GLuint buffer);
mcDrvError_t wcuGLMapBufferObjectAsync(mcDrvDeviceptrv1_t *dptr, unsigned int *size, GLuint buffer,
                                       mcDrvStream_t hStream);

/* TODO:wcuda_skipped - deprecated as of Cuda 5.0 */
mcDrvError_t wcuGLInit(void);
/* TODO:wcuda_skipped - deprecated as of Cuda 5.0 */
mcDrvError_t wcuGLRegisterBufferObject(GLuint buffer);
/* TODO:wcuda_skipped - deprecated as of Cuda 5.0 */
mcDrvError_t wcuGLUnmapBufferObject(GLuint buffer);
/* TODO:wcuda_skipped - deprecated as of Cuda 5.0 */
mcDrvError_t wcuGLUnregisterBufferObject(GLuint buffer);
/* TODO:wcuda_skipped - deprecated as of Cuda 5.0 */
mcDrvError_t wcuGLSetBufferObjectMapFlags(GLuint buffer, unsigned int Flags);
/* TODO:wcuda_skipped - deprecated as of Cuda 5.0 */
mcDrvError_t wcuGLUnmapBufferObjectAsync(GLuint buffer, mcDrvStream_t hStream);

/***************************cuda_gl_interop.h*******************************/
mcError_t wcudaGLGetDevices(unsigned int *pMacaDeviceCount, int *pMacaDevices,
                            unsigned int mcDeviceCount, enum mcGLDeviceList deviceList);
mcError_t wcudaGraphicsGLRegisterImage(struct mcGraphicsResource **resource, GLuint image,
                                       GLenum target, unsigned int flags);
mcError_t wcudaGraphicsGLRegisterBuffer(struct mcGraphicsResource **resource, GLuint buffer,
                                        unsigned int flags);
#ifdef _WIN32
mcError_t wcudaWGLGetDevice(int *device, HGPUNV hGpu);
#endif /* _WIN32 */

/* TODO:wcuda_skipped - deprecated as of Cuda 5.0 */
inline mcError_t wcudaGLSetGLDevice(int device) { return mcErrorNotSupported; }
/* TODO:wcuda_skipped - deprecated as of Cuda 5.0 */
inline mcError_t wcudaGLRegisterBufferObject(GLuint bufObj) { return mcErrorNotSupported; }
/* TODO:wcuda_skipped - deprecated as of Cuda 5.0 */
inline mcError_t wcudaGLMapBufferObject(void **devPtr, GLuint bufObj)
{
    return mcErrorNotSupported;
}
/* TODO:wcuda_skipped - deprecated as of Cuda 5.0 */
inline mcError_t wcudaGLUnmapBufferObject(GLuint bufObj) { return mcErrorNotSupported; }
/* TODO:wcuda_skipped - deprecated as of Cuda 5.0 */
inline mcError_t wcudaGLUnregisterBufferObject(GLuint bufObj) { return mcErrorNotSupported; }
/* TODO:wcuda_skipped - deprecated as of Cuda 5.0 */
inline mcError_t wcudaGLSetBufferObjectMapFlags(GLuint bufObj, unsigned int flags)
{
    return mcErrorNotSupported;
}
/* TODO:wcuda_skipped - deprecated as of Cuda 5.0 */
inline mcError_t wcudaGLMapBufferObjectAsync(void **devPtr, GLuint bufObj, mcStream_t stream)
{
    return mcErrorNotSupported;
}
/* TODO:wcuda_skipped - deprecated as of Cuda 5.0 */
inline mcError_t wcudaGLUnmapBufferObjectAsync(GLuint bufObj, mcStream_t stream)
{
    return mcErrorNotSupported;
}
#endif